package com.chcplayer
{
import com.chcplayer.enums.CHEventName;
import com.chcplayer.events.ViewZoomEvent;

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.Shader;
import flash.display.ShaderInput;
import flash.display.ShaderJob;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.ShaderFilter;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.getTimer;

/**
 * author yh
 */
public class ChcImage extends Sprite
{
	/**
	 */
	public static const s_bmdDashed:BitmapData = new BitmapData(2, 2);
	/**
	 */
	public static const TOP_CENTER_RATE:Number = 0.8;
	/**
	 */
	public static const ENLARGE_RATE:int = 1.5;
	/**
	 */
	public var $move:Function;
//--------------------------------------------------------------------------------------------------
// private
//--------------------------------------------------------------------------------------------------
	/**
	 */
	[Embed(source="Assets/Lens.pbj", mimeType="application/octet-stream")]
	private var m_cShader:Class;
	private var m_obFilter:ShaderFilter;
	/**
	 */
	private var m_contSnapShot:Sprite = new Sprite();
	/**
	 */
	private var m_picSnapShot:Bitmap = new Bitmap();
	/**
	 * 背景
	 */
	private var m_contBg:Sprite = new Sprite();
	/**
	 */
	private var m_picBg:Bitmap = new Bitmap();
	/**
	 */
	private var m_contLens:Sprite = new Sprite();
	/**
	 * 前景
	 */
	private var m_contPic:Sprite = new Sprite();
	private var m_obPic:Bitmap = new Bitmap();
	/**
	 */
	private var m_obDashedBox:Shape = new Shape();
	/**
	 */
	private var m_obModel:ChcFileModel;
	/**
	 */
	private var m_blEditMode:Boolean;
	/**
	 */
	private var m_bmdTempBig:BitmapData;
	private var m_bmdBig:BitmapData;
	/**
	 */
	private var m_nLensRadius:int;
	/**
	 */
	public function ChcImage()
	{
		super();
		this._init();
	}
//--------------------------------------------------------------------------------------------------
// private
//--------------------------------------------------------------------------------------------------
	private function _init():void
	{
		s_bmdDashed.fillRect(new Rectangle(0,0,1,1), 0x00ff00ff);
		s_bmdDashed.fillRect(new Rectangle(1,1,1,1), 0x00ff00ff);
		/*
		*/
		m_obFilter = new ShaderFilter( new Shader(new m_cShader() ) );
		m_contSnapShot.addChild(m_picSnapShot);
		this.addChild(m_contSnapShot);
		/*
		*/
		m_contBg.addChild(m_picBg);
		m_contLens.addChild(m_contBg);
		//@
		m_contPic.addChild(m_obPic);
		m_contLens.addChild(m_contPic);
		this.addChild(m_contLens);
		/*
		*/
		m_obDashedBox.blendMode = BlendMode.INVERT;
		this.addChild(m_obDashedBox);
		/*
		*/
		this.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown_this);
		this.addEventListener(MouseEvent.RIGHT_MOUSE_DOWN, rightMouseDown_this);
		m_contPic.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown_pic);
	}
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// events
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
	/**
	 */
	private function rightMouseDown_this(e:MouseEvent):void
	{
		this.startDrag();
		this.stage.addEventListener(MouseEvent.RIGHT_MOUSE_UP, mouseUp_stage);
	}
	/**
	 */
	private function mouseDown_this(e:MouseEvent):void
	{
		if ( m_blEditMode || e.ctrlKey )
		{
			this.startDrag();
			this.stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp_stage);
		}
		else if ( m_picBg.bitmapData != null )
		{
			/*查看模式
			*/
			this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove_stageLens);
			this.addChild(m_contLens);
			this.addChild(m_obDashedBox);
			/*
			*/
			m_obDashedBox.x = m_contLens.mouseX;
			m_obDashedBox.y = m_contLens.mouseY;
			this.stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove_stageDash);
			this.stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp_stageDash);
		}
	}
	/**
	 */
	private function mouseMove_stageLens(e:MouseEvent):void
	{
		var obMatrix:Matrix = new Matrix();
		var nScale:Number = 1 / m_contBg.scaleX;
		if ( null == m_picSnapShot.bitmapData )
		{
			m_picSnapShot.bitmapData = new BitmapData(Math.round(m_contBg.width*nScale), Math.round(m_contBg.height*nScale));
			obMatrix.createBox(nScale, nScale);
			m_picSnapShot.bitmapData.draw(m_contLens, obMatrix);
		}
		if ( null == m_bmdBig )
		{
			m_bmdBig = new BitmapData(m_contBg.width, m_contBg.height);
			obMatrix.createBox(1, 1);
			m_bmdBig.draw(m_contLens, obMatrix);
		}
		var nZoom:Number = this.scaleX * m_contBg.scaleX;
		var obShader:Shader = m_obFilter.shader;
		var nX:int = m_picSnapShot.mouseX;
		var nY:int = m_picSnapShot.mouseY;
		/*
		*/
		var nTopCenterR:int = m_nLensRadius * TOP_CENTER_RATE;
		var nBCenterR:int = nTopCenterR * m_contBg.scaleX;
		var nBottomW:int = nX * m_contBg.scaleX + nBCenterR;
		var nBottomH:int = nY * m_contBg.scaleY + nBCenterR;
		/*
		*/
		var nTopW:int = nX + nTopCenterR;
		var nTopH:int = nY + nTopCenterR;
		var nOffset:int = nTopCenterR * (m_contBg.scaleX-1);
		/*
		*/
		var nT:Number = getTimer();
		if ( 1 == nZoom )
		{
			obShader.data.offset.value = [nBottomW-nTopW-nOffset, nBottomH-nTopH-nOffset];
			obShader.data.pic.input = m_bmdBig;
		}
		else if ( nBottomW > 0 && nBottomH > 0 )
		{
			obShader.data.offset.value = [0, 0];
			if ( m_bmdTempBig != null )
			{
				m_bmdTempBig.dispose();
			}
			m_bmdTempBig = new BitmapData(nBottomW * nZoom * nScale, nBottomH * nZoom * nScale);
			var picTemp:Bitmap = new Bitmap(m_bmdBig);
			/*
			*/
			obMatrix.createBox(nZoom, nZoom, 0, (nTopW-nBottomW+nOffset)*nZoom, (nTopH-nBottomH+nOffset) * nZoom );
			m_bmdTempBig.draw(picTemp, obMatrix);
			/*
			*/
			obShader.data.pic.input = m_bmdTempBig;
		}
		obShader.data.bottom.value = [TOP_CENTER_RATE * nScale];
		obShader.data.top.value = [TOP_CENTER_RATE];
		obShader.data.center.value = [nX*nZoom, nY*nZoom];
		obShader.data.radius.value = [m_nLensRadius * nZoom];
		m_contSnapShot.filters = [m_obFilter];
		e.updateAfterEvent();
		this.$move( getTimer() - nT );
	}
	/**
	 */
	private function mouseMove_stageDash(e:MouseEvent):void
	{
		m_obDashedBox.graphics.clear();
		m_obDashedBox.graphics.beginBitmapFill(s_bmdDashed);
		var nW:int = m_obDashedBox.mouseX;
		var nH:int = m_obDashedBox.mouseY;
		m_obDashedBox.graphics.drawRect(0, 0, nW, nH);
		m_obDashedBox.graphics.drawRect(1, 1, nW-2, nH-2);
		m_nLensRadius = (nW > nH ? nH : nW) >> 1;
		var nX:int = nW >> 1;
		var nY:int = nH >> 1;
		m_obDashedBox.graphics.drawCircle(nX, nY, m_nLensRadius);
		m_obDashedBox.graphics.drawCircle(nX, nY, m_nLensRadius - 2 );
		/*
		*/
		m_nLensRadius = m_nLensRadius * ENLARGE_RATE / m_contBg.scaleX; 
		m_nLensRadius = Math.abs(m_nLensRadius);
	}
	/**
	 */
	private function mouseUp_stageDash(e:MouseEvent):void
	{
		this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove_stageDash);
		this.stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUp_stageDash);
		var nW:int = Math.abs(m_obDashedBox.width);
		var nH:int = Math.abs(m_obDashedBox.height);
		if ( nW > 0 && nH > 0 )
		{
			this.stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove_stageLens);
			m_obDashedBox.graphics.clear();
			this.removeChild(m_contLens);
			mouseMove_stageLens(e);
		}
	}
	/**
	 */
	private function mouseDown_pic(e:MouseEvent):void
	{
		if ( m_blEditMode )
		{
			e.stopImmediatePropagation();
			m_contPic.startDrag();
			this.stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp_stagePic);
		}
	}
	/**
	 */
	private function mouseUp_stagePic(e:MouseEvent):void
	{
		this.stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUp_stagePic);
		m_contPic.stopDrag();
		m_obModel.setPicLocation(m_contPic.x, m_contPic.y);
	}
	/**
	 */
	private function mouseUp_stage(e:MouseEvent):void
	{
		this.stage.removeEventListener(MouseEvent.RIGHT_MOUSE_UP, mouseUp_stage);
		this.stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUp_stage);
		this.stopDrag();
	}
//==================================================================================================
// public
//==================================================================================================
	/**
	 */
	public function setScaling(nS:Number):void
	{
		m_contBg.scaleX = m_contBg.scaleY = nS;
		m_picSnapShot.scaleX = m_picSnapShot.scaleY = nS;
		/*
		*/
		this.scaleX = this.scaleY = 1/ nS;
	}
	/**
	 */
	public function setBgRectEx(rect:Rectangle):void
	{
		m_picBg.x = rect.x;
		m_picBg.y = rect.y;
		m_contBg.graphics.clear();
		m_contBg.graphics.beginFill(m_obModel.getBgColor());
		var nW:int = m_picBg.width;
		var nH:int = m_picBg.height;
		m_contBg.graphics.drawRect(0, 0, nW + rect.right, nH + rect.bottom);
	}
	/**
	 */
	public function setPicLocation(obP:Point):void
	{
		m_contPic.x = obP.x;
		m_contPic.y = obP.y;
	}
	/**
	 */
	public function setEditMode(bl:Boolean):void
	{
		if ( m_blEditMode != bl )
		{
			m_blEditMode = bl;
			if ( bl )
			{
				this.addChild(m_contLens);
				this.addChild(m_obDashedBox);
				this.clearTempData();
			}
		}
	}
	/**
	 * 放大
	 */
	public function zoomIn():void
	{
		var eventV:ViewZoomEvent = new ViewZoomEvent(ViewZoomEvent.VIEW_ZOOM, this.scaleX, this.width, this.height);
		this.scaleX = this.scaleY = this.scaleX * 2;
		this.dispatchEvent(eventV);
	}
	/**
	 */
	public function zoomOut():void
	{
		var eventV:ViewZoomEvent = new ViewZoomEvent(ViewZoomEvent.VIEW_ZOOM, this.scaleX, this.width, this.height);
		this.scaleX = this.scaleY = this.scaleX / 2;
		this.dispatchEvent(eventV);
	}
	/**
	 */
	public function fitBgScale():void
	{
		var eventV:ViewZoomEvent = new ViewZoomEvent(ViewZoomEvent.FIT_BG_SCALE, scaleX, this.width, this.height);
		this.scaleX = this.scaleY = 1 / m_contBg.scaleX;
		this.dispatchEvent(eventV);
	}
	/**
	 */
	public function fitFgScale():void
	{
		var eventV:ViewZoomEvent = new ViewZoomEvent(ViewZoomEvent.FIT_FG_SCALE, scaleX, this.width, this.height);
		this.scaleX = this.scaleY = 1;
		this.dispatchEvent(eventV);
	}
	/**
	 */
	public function setBgBmd(bmd:BitmapData):void
	{
		m_picBg.bitmapData = bmd;
	}
	/**
	 */
	public function setPicBmd(bmd:BitmapData):void
	{
		m_obPic.bitmapData = bmd;
	}
	/**
	 */
	public function clearTempData():void
	{
		m_contSnapShot.filters = null;
		if ( this.stage )
		{
			this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove_stageLens);
		}
		if ( m_picSnapShot.bitmapData != null )
		{
			m_picSnapShot.bitmapData.dispose();
			m_picSnapShot.bitmapData = null;
		}
		if ( m_bmdBig != null )
		{
			m_bmdBig.dispose();
			m_bmdBig = null;
		}
	}
	/**
	 */
	public function setModel(obM:ChcFileModel):void
	{
		m_obModel = obM;
	}
	/**
	 */
}
}